package cn.brickie.singleton;

/***
 * 双检锁/双重校验锁（DCL，即 double-checked locking）

 * JDK版本：JDK1.5 起
 * 是否Lazy初始化：是
 * 是否多线程安全：是
 * 实现难度：较复杂
 * 描述：这种方式采用双锁机制，安全且在多线程情况下能保持高性能。
 * getInstance() 的性能对应用程序很关键。
 *
 * volatile 修饰理解:
 *   1. 当 线程1 执行到 #1 时，CPU便切换为 线程2 执行，线程2 也执行到 #1 ，此时 线程1、2 同时停留在#1
 *   2. 此时CPU切换为 线程1 执行 #2、#3、#4 完成后，释放锁
 *   3. 此时CPU切换为 线程2 执行 #2 时因为 线程1 创建的实例未能实时同步，此时 singleton 为空，故 线程2 同时能顺利执行完成 #3 到 #4
 *
 *   因为线程未能实现同步对象，所以导致对象二次创建，如对对像加以volatile修饰即可达到对象实时同步
 *
 * @author Brickie
 * @date 2018/5/30 11:55
 */
public class SingletonLayzSafeDCL {

    private volatile static SingletonLayzSafeDCL singleton;

    private SingletonLayzSafeDCL() {
    }

    public static SingletonLayzSafeDCL getSingleton() {
        if (singleton == null) {
            // #1
            synchronized (SingletonLayzSafeDCL.class) {
                // #2
                if (singleton == null) {
                    // #3
                    singleton = new SingletonLayzSafeDCL();
                }
            }
            // #4
        }
        return singleton;
    }
}
